Preparando o ambiente de desenvolvimento

Introdução

Os computadores não compreendem linguagens de programação diretamente; elas precisam ser convertidas para a linguagem de máquina, composta apenas por 0s e 1s (binário), que é a única linguagem que o computador entende. Para converter um código em linguagem de máquina, dependendo da linguagem de programação, é usado um processo que pode ser de compilação ou de interpretação.

Linguagens de programação compiladas são aquelas em que o código-fonte é traduzido para código de máquina antes da execução do programa. Esse processo é realizado por um compilador, um programa que analisa o código-fonte e o converte em instruções diretamente compreensíveis pela arquitetura da máquina alvo. Essa tradução antecipada permite que o programa seja executado com eficiência e rapidez, uma vez que as instruções já foram processadas e otimizadas antes da execução.

Por outro lado, linguagens de programação interpretadas não são traduzidas para código de máquina antes da execução. Em vez disso, um interpretador analisa o código-fonte linha por linha durante a execução do programa. Isso significa que cada vez que o programa é executado, o interpretador deve analisar e traduzir novamente o código-fonte para instruções compreensíveis pela máquina. Embora esse processo possa ser mais lento em comparação com a compilação, as linguagens interpretadas oferecem maior portabilidade, pois o mesmo código-fonte pode ser executado em diferentes sistemas operacionais e arquiteturas, desde que haja um interpretador disponível para a linguagem em questão.

diferença entre compilador e interpretador

Algumas linguagens, como Python e JavaScript (JS), usam uma abordagem intermediária entre compilação e interpretação. Nesses casos, o código-fonte é primeiro compilado para um formato de baixo nível chamado bytecode (imagem: arquivo de texto para arquivo de bytecode). O bytecode é uma representação binária das instruções que a máquina virtual específica da linguagem pode entender. Em seguida, a máquina virtual, é responsável por executar esse bytecode. Dessa forma, o código-fonte é traduzido apenas uma vez para bytecode e depois pode ser executado por diferentes máquinas virtuais em diferentes plataformas, proporcionando a portabilidade das linguagens interpretadas sem a necessidade de interpretar o código-fonte linha por linha repetidamente.

Bytecodes permitem aplicar a técnica de compilação Just-In-Time (JIT). A compilação JIT ocorre em tempo de execução, isto é, durante a execução do bytecode, em vez de ser realizada antecipadamente, como na compilação tradicional. Durante a execução, um compilador JIT analisa o bytecode e traduz partes do código em código de máquina otimizado para a arquitetura específica do computador em que está sendo executado. Esse código de máquina é armazenado em cache para reutilização em futuras execuções do mesmo trecho de código, evitando a necessidade de recompilação repetitiva.

A execução de partes específicas do código otimizado em código de máquina pode melhorar significativamente o desempenho em comparação com a interpretação linha por linha ou a execução de bytecode não compilado para código de máquina. A compilação JIT também permite que a linguagem de programação forneça uma combinação de portabilidade e eficiência, pois o mesmo código-fonte pode ser executado em diferentes plataformas, mas o compilador JIT pode gerar código de máquina otimizado para cada plataforma específica.

Executando Javascript via navegador web

Como as páginas web utilizam HTML+CSS+JavaScript, um bom navegador web moderno já vem com o interpretador de JavaScript instalado. Para executar códigos JavaScript, acesse as Ferramentas do Desenvolvedor do teu navegador web de preferência (na maioria dos navegadores, o atalho é a tecla F12), e abra a aba "Console". Esta aba é um terminal interativo, onde os comandos podem ser inseridos e executados um de cada vez.

Instalando um ambiente de execução Javascript

Um Ambiente de Execução (Runtime Enviroment) é um kit com tudo que precisamos, como a máquina virtual e o compilador JIT, para desenvolver e executar aplicativos de uma determinada linguagem de programação. Para o JavaScript, instalaremos o ambiente de execução Node.js (node). Assim, conseguimos desenvolver e executar programas JavaScript sem a necessidade de um navegador web. O Node.js vem com o Node Package manager (npm), que é uma ferramenta que permite baixar, instalar e gerenciar pacotes de terceiros. Pacotes de terceiros são projetos desenvolvidos por outros desenvolvedores e que podem ser adicionados ao seu próprio projeto.

Siga os passos da seção correspondente ao teu sistema operacional, seja Linux ou Windows, a seguir:

Linux

Vamos instalar o Node Version Manager (nvm) e usá-lo para instalar o node e o npm. Recomendamos o uso de um gerenciador de versões, pois as versões mudam muito rapidamente. Você provavelmente precisará alternar entre várias versões do node com base nas necessidades dos diferentes projetos em que está trabalhando. O Node Version Manager (nvm) é um gerenciador de versões do node muito popular.

É sempre recomendável remover qualquer instalação existente do node ou npm antes de instalar um gerenciador de versões, pois diferentes tipos de instalação podem levar a conflitos.

  1. Instale o nvm: wget -O - https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash.
  2. Verifique se o nvm foi instalado (talvez seja necessário reiniciar o terminal): nvm --version. Deve aparecer a versão instalada do nvm, que, nesta data, é 0.39.7.
  3. Liste as versões disponíveis do node: nvm ls.
  4. Confirme que nenhuma versão do node está instalada: nvm use node. Deve aparecer algo como "not yet installed".
  5. Instale a versão LTS estável atual do node (recomendada para aplicativos em produção): nvm install --lts.
  6. Verifique se o node foi instalado: node --version. Verifique também se o npm foi instalado junto com o node: npm --version.
  7. Para alterar a versão do node, por exemplo, para a versão 18.2.0: nvm use v18.2.0. Lembrando que a versão deve estar instalada antes de mudar para ela. Para alterar para a última versão LTS: nvm use --lts.

Windows

Siga uma das seguintes alternativas:

  • (fácil) Baixe e instale o node pelo site oficial.
  • ou

  • (difícil) Instale o Windows Subsystem for Linux (WSL): https://learn.microsoft.com/en-us/windows/wsl/install. Depois, siga o tutorial de instalação do NodeJS para Windows: https://learn.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl.
  • Ambiente de desenvolvimento integrado

    Para facilitar o desenvolvimento de programas em JavaScript, usaremos o Visual Studio Code (vscode). Trata-se de um Ambiente de Desenvolvimento Integrado (IDE) que integra recursos para escrever, depurar, compilar e gerenciar dependências de código em um único lugar. Você pode baixar o VSCode aqui.

    Já com o JavaScript instalado, abra o vscode e acesse a aba de extensões (atalho Ctrl + Shift + X). Em seguida, instale as seguintes extensões:

    Criando nosso projeto

    É fundamental mantermos nosso ambiente de trabalho organizado. Como programadores, separamos nossos códigos em projetos, que são pastas que agrupam nossos arquivos de código.

    Vamos baixar um projeto já configurado do GitHub. O GitHub é um site que hospeda repositórios Git, onde os desenvolvedores podem armazenar, compartilhar e colaborar em projetos. Você pode baixar e abrir o projeto de duas maneiras. Se você não tem o git instalado ou não está familiarizado com o git, siga as etapas da Alternativa 2. Se você tiver o git instalado, siga as etapas da Alternativa 1.

    Alternativa 1

    1. Copie este link: https://github.com/pedrosiqueira/info3-dw3.git.
    2. No vscode, tecle F1, digite "clone" e selecione a opção "Git: Clone".
    3. Na caixa de entrada que aparece, cole o link copiado anteriormente e tecle Enter.
    4. Escolha um local para o seu projeto e abra-o no vscode.
    5. Se aparecer uma mensagem perguntando se você confia neste projeto, confirme que sim.

    Alternativa 2

    1. Baixe o projeto do link https://github.com/pedrosiqueira/info3-dw3/archive/refs/heads/main.zip.
    2. O arquivo baixado está compactado em .zip. Descompacte o arquivo no local onde deseja armazenar seu projeto.
    3. Abra o projeto no vscode (atalho Ctrl+k Ctrl+o).

    De início, o projeto vem com dois arquivos de configuração. O arquivo .vscode/launch.json possui configurações do vscode para o projeto, como como compilá-lo e executá-lo. O arquivo package.json possui configurações do node para o projeto, como o nome dos autores do projeto, descrição do projeto, e pacotes de terceiros utilizados pelo projeto.

    O projeto também vem com a pasta node_modules, onde ficam os pacotes de terceiros. No momento o único pacote que utilizaremos é o scanf, que nos auxilia a ler dados digitados pelo usuário.

    Organizaremos nosso projeto por pastas. Criaremos uma pasta para cada capítulo, onde colocaremos os códigos desenvolvidos naquele capítulo. Como estamos no segundo capítulo, crie a pasta cap02 na pasta raiz do projeto. Você pode fazer isso no vscode clicando com o botão direito no espaço vazio da aba de explorador e selecionando "New folder...".

    Agora, crie o arquivo hello-world.js dentro da pasta cap02. Você pode fazer isso no vscode clicando com o botão direito em cima da pasta cap02 e selecionando "New file...". Observe que todos os arquivos de código-fonte em JavaScript devem terminar com a extensão .js.

    Escreva o código console.log('hello, world!') dentro do arquivo recém-criado. Para executar esse arquivo, abra o terminal na pasta raiz do projeto (atalho Ctrl+j) e execute node cap02/hello-world.js. Parabéns, esse é seu primeiro programa em JavaScript!

    Você também pode executar qualquer arquivo .js aberto no vscode simplesmente teclando F5.

    Extras (não cai na prova)

    Configuração do Node.js

    O npm instala pacotes por usuário, mas em computadores com vários usuários, é possível compartilhar a mesma pasta de pacotes para economizar espaço em disco. Para isso, podemos modificar as configurações padrão do npm que definem onde os pacotes são instalados. Existem duas principais formas de configurar o npm: editando os arquivos npmrc ou definindo variáveis de ambiente do sistema. Aqui, vamos definir variáveis de ambiente que redirecionam a instalação de pacotes globais e o cache do npm para as pastas C:\npm\ e C:\npm-cache\, respectivamente.

    No Windows, se não tiver acesso administrativo, execute pelo terminal os comandos da alternativa 1. Caso contrário, execute pelo terminal no modo administrativo os comandos da alternativa 2.

    Alternativa 1 (sem privilégios administrativos)

    [Environment]::SetEnvironmentVariable("npm_config_prefix", "${SYSTEMDRIVE}\npm\", "User")
    [Environment]::SetEnvironmentVariable("npm_config_cache", "${SYSTEMDRIVE}\npm-cache\", "User")

    Alternativa 2 (com privilégios administrativos)

    [Environment]::SetEnvironmentVariable("npm_config_prefix", "${SYSTEMDRIVE}\npm\", "Machine")
    [Environment]::SetEnvironmentVariable("npm_config_cache", "${SYSTEMDRIVE}\npm-cache\", "Machine")

    Debugging

    Errar faz parte do processo de aprendizagem, especialmente na programação. No entanto, às vezes é difícil encontrar a fonte de um erro no código. É aí que entra a arte de debugging. Debugging, ou depuração de código, é o processo de identificar, isolar e corrigir erros em um programa de computador. Quando um programa apresenta comportamentos inesperados, é necessário depurar o código para encontrar e resolver o problema. Isso envolve pausar a execução do programa, observar variáveis e valores em diferentes pontos do código e identificar onde ocorrem os erros. O debugging também é útil para entender o funcionamento do programa, permitindo que você o execute passo a passo, no seu próprio ritmo.

    Crie o arquivo cap02/factorials.js com o seguinte código:

    function calculateSumOfFactorials(argument1, argument2) {
        let factorial1 = calculateFactorial(argument1);
        let factorial2 = calculateFactorial(argument2);
        let result = calculateSum(factorial1, factorial2);
        return result;
    }
    
    function calculateFactorial(argument) {
        let factorialResult = 1;
        for (let i = 1; i <= argument; i++) {
            factorialResult *= i;
        }
        return factorialResult;
    }
    
    function calculateSum(argument1, argument2) {
        return argument1 + argument2;
    }
    
    let a = 5;
    let b = 10;
    let sumOfFactorials = calculateSumOfFactorials(a, b);
    console.log("The sum of factorials of the entered integers is", sumOfFactorials);

    (Observação: as barras em um caminho de arquivo significam as pastas onde o arquivo se encontra. Portanto, cap02/factorials.js significa que o arquivo factorials.js está dentro da pasta cap02).

    Veja se você consegue entender o que esse código está fazendo. Agora, antes de executá-lo de uma vez, experimente colocar um breakpoint na linha 20.

    Dentre as opções de depuração no vscode, você pode continuar a execução até o próximo breakpoint (F5), avançar (F10), entrar (F11), sair (Shift + F11).

    Na aba de depuração, você pode ver os valores das variáveis atuais, definir observadores (watch) de variáveis ou expressões, consultar a pilha de chamadas de funções e os breakpoints.

    Na aba "Debug Console", você pode escrever linhas de códigos que são executadas no contexto do programa atual, com acesso às suas variáveis e funções.

    No momento, essas informações podem parecer abstratas se você ainda está no início de sua jornada como programador. No entanto, depurar é uma ferramenta essencial para programadores e, à medida que você aprender mais, tudo ficará mais claro e fará mais sentido. Por isso, convido você a revisitar essa seção após adquirir mais maturidade em programação. Com o tempo e o conhecimento adquirido, essas práticas e termos farão mais sentido e serão uma parte natural do teu fluxo de trabalho como desenvolvedor.

    Criando seu projeto do zero

    Anteriormente, vimos como baixar um projeto já configurado e pronto para uso. Aqui faremos o passo a passo para criar e configurar o projeto do zero.

    Parte do vscode

    1. Crie uma pasta para o projeto. Essa pasta é conhecida como "pasta raiz", pois todos os arquivos do projeto ficam dentro dela.
    2. Abra essa pasta pelo vscode (atalho Ctrl+k Ctrl+o).
    3. Acesse o menu "Run → Add Configuration → Node.js". Isso adiciona uma configuração do vscode ao seu projeto para conseguir executar seus scripts simplesmente teclando F5, sem precisar digitar comandos no terminal.
    4. No arquivo recém-criado .vscode/launch.json, adicione a linha "console": "integratedTerminal", logo acima da linha "type":"node",. Essa linha configura o vscode para executar os arquivos pelo terminal em vez do debug console, pois assim poderemos interagir com nossos programas.

    Parte do node

    1. Embora o npm seja o gerenciador de pacotes padrão do node, eu pessoalmente prefiro o gerenciador de pacotes pnpm, por ser mais ágil e ocupar menos espaço que o npm. Para instalar o pnpm, basta executar npm install -g pnpm.
    2. Uma vez instalado o pnpm, vamos configurar nosso projeto para ser gerenciado pelo pnpm. Dentro da pasta raiz do projeto, execute pnpm init. É criado um arquivo package.json, que contém informações do teu projeto, como os pacotes que ele depende para ser executado.
      • (Observação: Se estiver no Windows e o comando anterior der um erro de permissão de execução de scripts pelo terminal powershell, abra um powershell como administrador e execute Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser. Feche todos os terminais, reabra um terminal na pasta raiz do projeto e execute novamente pnpm init).
    3. Geralmente projetos grandes são compostos por vários arquivos de código-fonte, além dos pacotes de terceiros. O modo como o JavaScript estrutura e utiliza os arquivos é chamado de module system. Basicamente há dois sistemas de módulo: o CommonJS, que é mais antigo e vem habilitado por padrão; e o ECMAScript Modules (ESM), que é mais recente e vamos substituir pelo antigo. Para tanto, adicione a linha "type": "module", no arquivo package.json.
    4. O node não vem com uma maneira simples de ler entradas digitadas pelo terminal, pelo fato do foco do JavaScript ser desenvolvimento web. Mas para fins de aprendizado de algoritmos, é mais fácil interagirmos com nossos programas diretamente pelo terminal. Portanto, vamos instalar o utilitário de leitura de entradas por terminal node-scanf. Execute pnpm add scanf na pasta raiz do projeto. Ao instalar um pacote com o pnpm, o pacote é colocado na pasta node_modules e também registrado no arquivo package.json.
    5. Por fim, para testar se está tudo em ordem, crie e execute o arquivo cap02/input-output.js com o seguinte código:
    import scanf from 'scanf';
    
    console.log('Please input your name');
    let name = scanf('%s');
    
    console.log('Please input your age');
    let age = scanf('%d');
    
    console.log('your name', name, 'is a', typeof name);
    console.log('your age', age, 'is a', typeof age);

    Não se preocupe em entender tudo o que está se passando. Esse capítulo é mais para deixar tudo preparado para começarmos a aprender JavaScript no próximo capítulo. Se este programa estiver funcionando conforme o esperado, ele vai te solicitar um nome e uma idade, e, depois que você informá-los, o programa responde com algumas mensagens.